﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;

namespace Nexxo.Channel.DMS.Web
{
    //DefaultAttribute
    public class DefaultAttribute : ValidationAttribute, IClientValidatable
    {
        public string DefaultValue { get; set; }
        public string DependingProperty { get; set; }
        public string DependingPropertyValue { get; set; }
        public string CurrentProperty { get; set; }
        public bool IsRequired { get; set; }

        public DefaultAttribute(string defaultValue, string currentProperty,bool isRequired, string dependingProperty = "", string dependingPropertyValue = "")
            : base("{0} is required.")
        {
            DefaultValue = defaultValue;
            DependingProperty = dependingProperty;
            DependingPropertyValue = dependingPropertyValue;
            CurrentProperty = currentProperty;
            IsRequired = isRequired;
        }

        protected override ValidationResult IsValid(object value, ValidationContext context)
        {
            var cProperty = context.ObjectInstance.GetType().GetProperty(CurrentProperty);

            if (cProperty != null)
            {
                if (cProperty.GetCustomAttributes(typeof(RequiredAttribute), true).Length > 0)
                {
                    if (DependingProperty != "" && DependingPropertyValue != "")
                    {
                        var curruntProperty = context.ObjectInstance.GetType().GetProperty(DependingProperty);
                        var curruntPropertyValue = curruntProperty.GetValue(context.ObjectInstance, null);

                        if (curruntPropertyValue.Equals(DependingPropertyValue) && value.Equals(DefaultValue))
                        {
                            if (!string.IsNullOrEmpty(ErrorMessage))
                                return new ValidationResult(ErrorMessage);
                            else
                                return new ValidationResult(FormatErrorMessage(context.DisplayName));
                        }
                    }
                    else if (value.Equals(DefaultValue))
                    {
                        if (!string.IsNullOrEmpty(ErrorMessage))
                            return new ValidationResult(ErrorMessage);
                        else
                            return new ValidationResult(FormatErrorMessage(context.DisplayName));
                    }
                }
            }
            return ValidationResult.Success;
        }

        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
             return new[] { new ModelClientValidationSelectOneRule(FormatErrorMessage(metadata.DisplayName), DefaultValue, DependingProperty, DependingPropertyValue, IsRequired) };
        }
    }

    public class ModelClientValidationSelectOneRule : ModelClientValidationRule
    {
        public ModelClientValidationSelectOneRule(string errorMessage, string defaultValue, string dependingProperty, string dependingPropertyValue, bool isRequired) 
        {
            ErrorMessage = errorMessage;
            ValidationType = "mycustomvalidation";
            ValidationParameters.Add("defaultvalue", defaultValue);
            ValidationParameters.Add("dependingproperty", dependingProperty);
            ValidationParameters.Add("dependingpropertyvalue", dependingPropertyValue);
            ValidationParameters.Add("isrequired", isRequired);
        }
    }

    //DateRangeAttrbute CustomValidation
    public class DateRangeAttribute : ValidationAttribute, IClientValidatable
    {
        public int MinDate { get; set; }
        public int MaxDate { get; set; }

        /// <summary>
        /// For validating the datetime past dates, and feature dapending on the parameter you pass. For past passitive numbers, For feature negative numbers.
        /// </summary>
        /// <param name="minimum">if u pass +ve that means past back that number of years ago, if u pass +ve that means feature that number of years later</param>
        /// <param name="maximum">if u pass +ve that means past back that number of years ago, if u pass +ve that means feature that number of years later</param>
        public DateRangeAttribute(int minimum, int maximum)
            : base("{0} is not valid.")
        {
            MinDate = minimum;
            MaxDate = maximum;
        }

        protected override ValidationResult IsValid(object value, ValidationContext context)
        {
            if (!(Convert.ToDateTime(value.ToString()) < DateTime.Now.AddYears(-(MinDate)) && DateTime.Now.AddYears(-(MaxDate)) < Convert.ToDateTime(value.ToString())))
            {
                if (!string.IsNullOrEmpty(ErrorMessage))
                    return new ValidationResult(ErrorMessage);
                else
                    return new ValidationResult(FormatErrorMessage(context.DisplayName));
            }
            return ValidationResult.Success;
        }

        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            return new[] { new ModelDateValidationSelectOneRule(FormatErrorMessage(metadata.DisplayName), MinDate, MaxDate) };
        }
    }

    public class ModelDateValidationSelectOneRule : ModelClientValidationRule
    {
        public ModelDateValidationSelectOneRule(string errorMessage, int minValue, int maxValue)
        {
            ErrorMessage = errorMessage;
            ValidationType = "mydatecustomvalidation";
            ValidationParameters.Add("minvalue", minValue);
            ValidationParameters.Add("maxvalue", maxValue);
        }
    }
}